package com.zz.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zz.common.ESignParameter;
import com.zz.common.EsignHttpResponse;
import com.zz.common.FileTransformation;
import com.zz.common.ZohoRecord;
import com.zz.service.IncentiveService;
import com.zz.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class IncentiveServiceImpl implements IncentiveService {


    @Autowired
    ZohoRecord zohoRecord;

    @Autowired
    ESignParameter parameter;

    // 当前环境
    public static final String environment = ESignParameter.ENVIRONMENT;


    @Override
    public ResultUtil electronicSignatureIncentive(String incentiveId, String operationId) {
        log.info("开发上量奖励模块,生成电子签章入参,incentiveId = {},operationId = {}", incentiveId, operationId);
        if (StringUtils.isBlank(incentiveId) || StringUtils.isBlank(operationId)) {
            return ResultUtil.error("入参为空");
        }
        ResultUtil resultUtil;
        // crm数据
        JSONObject incentiveData = BiologicalApiUtil.getIncentiveData(zohoRecord.getAccessToken(), incentiveId);

        if (Objects.nonNull(incentiveData)) {
            //1 获取accountId
            resultUtil = generatorAccount(incentiveData);
            if (!resultUtil.getCode().equals(200)) {
                return resultUtil;
            }
            List<Map<String, Object>> mapList = (List<Map<String, Object>>) resultUtil.getData();
            List<Map<String, Object>> newMapList = new ArrayList<>();
            //2 文件doc ——> PDF
            boolean isCheck = false;
            List<JSONObject> userData = CrmApiUtil.getUserDataById(zohoRecord.getAccessToken(), operationId);
            if (!CollectionUtils.isEmpty(userData)) {
                JSONObject user = userData.get(0);
                JSONObject profile = user.getJSONObject("profile");
                if (Objects.nonNull(profile)) {
                    String roleName = profile.getString("name");
                    log.info("当前用户角色名称 = " + roleName);
                    if (roleName.equalsIgnoreCase("客服助理") ||
                            roleName.equalsIgnoreCase("发货组客服组长") ||
                            roleName.equalsIgnoreCase("购销服务部经理") ||
                            roleName.equalsIgnoreCase("系统管理员") ||
                            roleName.equalsIgnoreCase("Administrator")) {
                        isCheck = true;
                    }
                }
            }

            if (isCheck) {
                log.info("===== 第二步【文件doc ——> PDF】=====");

                // 乙方-签约人
                JSONObject two_part1_c = incentiveData.getJSONObject("Two_Part1_c");
                String fileName = two_part1_c.getString("name");

                JSONObject contract_c = incentiveData.getJSONObject("Contract_c");
                String contractName = contract_c.getString("name");

                fileName += contractName.replace('\\', '-').replace('/', '-').replace(':', '-').replace('∶', '-').replace('：', '-').replace('*', '-').replace('"', '-').replace('<', '-').replace('>', '-').replace('|', '-').replace('?', '-') + ".PDF";
                ResultUtil<String> generatorPDFResult = generatorPDF(incentiveData);
                if (200 == generatorPDFResult.getCode()) {

                    // 甲、乙、丙 轮流签字
                    //System.out.println("JSON.toJSONString(mapList) = " + JSON.toJSONString(mapList));
                    for (Map<String, Object> personMap : mapList) {
                        //3 根据关键字获取X、Y
                        log.info("===== 第三步【根据关键字获取X、Y】=====");
                        String fileId = generatorPDFResult.getData();
                        //System.out.println("fileId = " + fileId);
                        String keyWord = "";
                        if ((Integer) personMap.get("typeName") == 1) {
                            keyWord = "甲方(签字)";
                        } else if ((Integer) personMap.get("typeName") == 2) {
                            keyWord = "乙方(签字)";
                        } else if ((Integer) personMap.get("typeName") == 3) {
                            keyWord = "丙方(签字)";
                        }

                        JSONObject keyWordPosition = ESignApiUtil.getKeyWordPosition(parameter, environment, fileId, keyWord);
                        log.info("搜索关键字坐标接口result = " + keyWordPosition.toJSONString());
                        if (0 == keyWordPosition.getInteger("code")) {
                            JSONArray data = keyWordPosition.getJSONArray("data");
                            List<JSONObject> list = data.toJavaList(JSONObject.class);
                            if (!CollectionUtils.isEmpty(list)) {
                                JSONObject jsonObject = list.get(0);
                                JSONArray positionList = jsonObject.getJSONArray("positionList");
                                List<JSONObject> position = positionList.toJavaList(JSONObject.class);
                                JSONObject jsonObject1 = position.get(0);
                                Integer pageIndex = jsonObject1.getInteger("pageIndex");
                                JSONArray coordinateList = jsonObject1.getJSONArray("coordinateList");
                                List<JSONObject> list1 = coordinateList.toJavaList(JSONObject.class);
                                JSONObject jsonObject2 = list1.get(0);
                                double posxTemp = jsonObject2.getDouble("posx") + 3.5 * 28.346;
                                int posx = (int) posxTemp;
                                double posyTemp = jsonObject2.getDouble("posy") + 0.5 * 28.346;
                                int posy = (int) posyTemp;

                                Map<String, Object> map = new HashMap<>(personMap);
                                map.put("pageIndex", pageIndex);
                                map.put("posx", posx);
                                map.put("posy", posy);
                                map.put("fileId", fileId);

                                newMapList.add(map);
                            } else {
                                return ResultUtil.error("请求关键字坐标接口失败");
                            }
                        }
                    }
                    //4 一步签署，回调
                    log.info("===== 第四步【一步发起签署】=====");
                    //System.out.println("JSON.toJSONString(newMapList) = " + JSON.toJSONString(newMapList));
                    ResultUtil<String> signResult = launchESign(incentiveData, fileName, newMapList);
                    if (200 == signResult.getCode()) {

                        log.info("已向客户手机发送短信，等待验证");
                        return ResultUtil.success("已向客户手机发送短信，等待验证");
                    } else {
                        return signResult;
                    }


                } else {
                    return generatorPDFResult;
                }
            } else {
                return ResultUtil.error("当前用户角色没有权限");
            }
        } else {
            return ResultUtil.error("开发上量奖励模块数据" + incentiveId + "为空");
        }
    }


    // 生成待签署PDF文件
    public ResultUtil<String> generatorPDF(JSONObject incentiveData) {

        ResultUtil<String> resultUtil = ResultUtil.success();

        List<JSONObject> allAttachmentList = CrmApiUtil.getAttachmentListByIncentive(zohoRecord.getAccessToken(), incentiveData.getString("id"));
        List<JSONObject> attachmentList = allAttachmentList.stream().filter(jsonObject -> jsonObject.getString("File_Name").contains(".doc")).collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(attachmentList)) {
            // 最近创建的一份奖励模板，且与奖励名称保持一致
            JSONObject attachment = new JSONObject();
            for (JSONObject jsonObject : attachmentList) {
                if (Objects.isNull(attachment.getString("Created_Time"))) {
                    attachment = jsonObject;
                } else {
                    String dataTime = attachment.getString("Created_Time");
                    String jsonTime = jsonObject.getString("Created_Time");
                    // 奖励名称
                    String incentiveName = incentiveData.getString("Name");
                    if (DateUtil.dateCompare(dataTime, jsonTime)
                            && jsonObject.getString("File_Name").contains(incentiveName)
                    ) {
                        attachment = jsonObject;
                    }
                }
            }

            InputStream attachmentStream = CrmApiUtil.downloadAttachmentByIncentice(zohoRecord.getAccessToken(), incentiveData.getString("id"), attachment.getString("id"));

            if (Objects.nonNull(attachmentStream)) {

                String filePath = FileUtil.getRelativeResourceFilePath();
                String fileName = DateUtil.getToday() + "_temp_" + ESignEncryptionUtil.generateSuffix() + ".doc";
                String fileFullPath = filePath + File.separator + fileName;
                System.out.println("fileFullPath = " + fileFullPath);
                //生成文件
                FileUtil.generatorFile(attachmentStream, fileFullPath);

                // 1 获取文件上传地址
                JSONObject data = new JSONObject();
                //Content-MD5计算方法
                String fileContentMd5 = ESignEncryptionUtil.getStringContentMD5(fileFullPath);

                String contentType = "application/octet-stream";
                data.put("contentMd5", fileContentMd5);
                data.put("contentType", contentType);
                data.put("convert2Pdf", true);
                String attachFileName = attachment.getString("File_Name");
                attachFileName = attachFileName.replace('\\', '-').replace('/', '-').replace(':', '-').replace('∶', '-').replace('：', '-').replace('*', '-').replace('"', '-').replace('<', '-').replace('>', '-').replace('|', '-').replace('?', '-').replace('+', '-');
                if (!attachFileName.contains(".doc")) {
                    attachFileName += ".doc";
                }
                data.put("fileName", attachFileName);
                data.put("fileSize", attachment.getIntValue("Size"));
                JSONObject uploadFileUrl = ESignApiUtil.getUploadFileUrl(parameter, environment, data);
                log.info("获取上传文件路径接口result = " + uploadFileUrl.toJSONString());
                if ("0".equals(uploadFileUrl.getString("code"))) {
                    JSONObject jsonData = uploadFileUrl.getJSONObject("data");
                    String uploadUrl = jsonData.getString("uploadUrl");
                    String fileId = jsonData.getString("fileId");

                    // 2 上传文件流（二进制字节流）
                    try {
                        //文件上传
                        EsignHttpResponse uploadFileResponse = ESignApiUtil.uploadFile(uploadUrl, fileFullPath);
                        if (Objects.nonNull(uploadFileResponse)) {
                            JSONObject jsonObject = JSONObject.parseObject(uploadFileResponse.getBody());
                            log.info("上传文件流接口result = " + jsonObject.toJSONString());
                            String code = jsonObject.getString("errCode");
                            if ("0".equals(code)) {
                                log.info("文件上传e签宝成功，状态码 = " + code);
                                //查询文件上传状态
                                boolean isContinue = true; // 是否继续查询文件
                                int time = 0;
                                do {
                                    JSONObject fileUploadStatus = ESignApiUtil.getFileUploadStatus(parameter, environment, fileId);
                                    if ("0".equals(fileUploadStatus.getString("code"))) {
                                        String fileStatus = fileUploadStatus.getJSONObject("data").getString("status");
                                        log.info(String.format("查询文件状态执行第%s次", time + 1));
                                        if ("2".equalsIgnoreCase(fileStatus) || "5".equalsIgnoreCase(fileStatus)) {//查询状态为2或者5代表文件准备完成
                                            log.info("文件已经生成");
                                            isContinue = false;
                                            resultUtil = ResultUtil.success(fileId);
                                        } else {
                                            log.info("文件未准备完成,等待两秒重新查询");
                                            TimeUnit.SECONDS.sleep(2);
                                            time++;
                                        }
                                    }
                                } while (isContinue);

                                // 生成PDF文件后，将合同模块的 签署文档转换状态 改为已完成
                                JSONObject updateData = new JSONObject();
                                updateData.put("PDFConvertStatus_c", "已完成"); // 署文档转换状态
                                CrmApiUtil.updateIncentiveData(incentiveData.getString("id"), updateData);
                            }
                        } else {
                            return ResultUtil.error("e签宝文件流上传失败");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // 删除temp文件
                    deleteTempFile();
                } else {
                    return ResultUtil.error("e签宝获取文件路径接口访问失败 = " + uploadFileUrl.toJSONString());
                }
            } else {
                return ResultUtil.error("CRM下载文件失败");
            }

        } else {
            return ResultUtil.error("该合同不存在附件");
        }
        return resultUtil;
    }

    // 验证 crm文件是否已经推送过e签宝
    public String checkIsPush(String crmFileId) {
        Properties properties = new Properties();
        ClassPathResource classPathResource = new ClassPathResource("fileId.properties");
        InputStream inputStream;
        try {
            inputStream = classPathResource.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            properties.load(bufferedReader);
            Set<Object> keySets = properties.keySet();
            for (Object obj : keySets) {
                if (crmFileId.equalsIgnoreCase((String) obj)) {
                    return (String) properties.get(obj);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    // 存储 crm文件id与e签宝id对应关系
    public void saveFileId(String crmFileId, String eFileId, String fileName) {
        String dir = System.getProperty("user.dir");
        String path = dir + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + fileName;

        Properties properties = new Properties();
        ClassPathResource classPathResource = new ClassPathResource(fileName);
        InputStream inputStream;
        try {
            inputStream = classPathResource.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            properties.load(bufferedReader);
            properties.setProperty(crmFileId, eFileId);
            properties.store(new FileWriter(path), null);
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public void deleteTempFile() {
        log.info("===== 【删除temp临时文件】 =====");
        // 1 获取所有文件
        List<File> allFile = FileUtil.getAllFile();

        for (File file : allFile) {

            String name = file.getName();
            if (name.contains("_temp_")) {
                if (file.delete()) {
                    log.info(name + " ——> 已经删除");
                }
            }
        }
    }

    public void deletePDFFile() {
        log.info("===== 【删除PDF临时文件】 =====");
        // 1 获取所有文件
        List<File> allFile = FileUtil.getAllFile();

        for (File file : allFile) {

            String name = file.getName();
            if (name.contains("PDF")) {
                if (file.delete()) {
                    log.info(name + " ——> 已经删除");
                }
            }
        }
    }

    // 销售经理 或 总监 去 用户模块查询
    public JSONObject getSaleDirectorData(String accessToken, String saleDirectorId) {
        JSONObject result = new JSONObject();
        List<JSONObject> basicFile = BiologicalApiUtil.getUserInfoSearch(accessToken, saleDirectorId);
        if (basicFile.size() > 0) {
            JSONObject jsonObject = basicFile.get(0);
            result.put("phone", jsonObject.getString("Phone")); // 手机号
            result.put("idNum", ""); // 身份证号
            result.put("accountId", jsonObject.getString("Sign_Account_ID")); // 签署账号Id
            return result;
        }
        return null;
    }

    // 签约人、乙方、丙方 去 基础档案模块查询
    public JSONObject getSignPeopleData(String accessToken, String peopleId) {

        List<JSONObject> basicFile = BiologicalApiUtil.getBasicFile(accessToken, peopleId);
        if (basicFile.size() > 0) {
            JSONObject result = new JSONObject();
            JSONObject jsonObject = basicFile.get(0);
            result.put("phone", jsonObject.getString("Phone")); // 手机号
            result.put("idNum", jsonObject.getString("IDNumber_c")); // 身份证号
            result.put("accountId", jsonObject.getString("accountId_c")); // 签署账号Id
            return result;
        }

        return null;

    }

    /**
     * 推送E签宝 创建个人签署账号
     *
     * @param json 推送数据
     *             id = 模块id
     *             name = 用户名称
     *             idNum = 身份证号
     *             phone = 手机号
     *             accountId = 签署账号Id
     *             type = 1：销售经理 或 总监；合同所有者；2：签约人、乙方、丙方、业务签约人
     *             typeName: 1:甲方、售经理 或 总监；2：乙方：3：丙方
     */
    @Override
    public ResultUtil callESignAccount(JSONObject json) {

        Map<String, Object> map = new HashMap<>();
        map.put("typeName", json.getInteger("typeName"));

        // 验证账号是否已经存在
        String accountId = json.getString("accountId");
        String id = json.getString("id");
        String name = json.getString("name");
        String idNum = json.getString("idNum");
        String phone = json.getString("phone");
        Integer type = json.getInteger("type");
        //if (StringUtils.isNotBlank(accountId)) {  // 即使有accountId,用户有可能修改手机号，这个accountid就不好用了，要重新推送
        //    log.info("id ={},name={}的账户已推送", id, name);
        //    log.info("===== 第一步【获取accountId】 =====");
        //    log.info("accountId = " + accountId);
        //    map.put("accountId", accountId);
        //    return ResultUtil.success(map);
        //}

        JSONObject account = ESignApiUtil.createAccount(parameter, environment, id, name, phone);
        log.info("创建个人账号接口result = " + account.toJSONString());

        if (account.getInteger("code") != 0) {
                log.info("id ={},name={}的账户已推送", id, name);
                log.info("===== 第一步【获取accountId】 =====");
                log.info("accountId = " + accountId);
                map.put("accountId", accountId);
                return ResultUtil.success(map);
        }

        JSONObject data = account.getJSONObject("data");
        String newAccountId = data.getString("accountId");
        log.info("===== 第一步【获取accountId】 =====");
        log.info("accountId = " + newAccountId);

        // 存储 accountId
        Map<String, Object> paramsMap = new HashMap<>();
        JSONArray updateData = new JSONArray();
        JSONObject jsonObject = new JSONObject();

        String url = "";

        if (type == 1) { // 用户信息

            // 返回的id 是【用户ID】字段，search此字段返回模块id
            String searchUrl = "https://www.zohoapis.com.cn/crm/v3/User_Profile/search?criteria=(User_ID:equals:" + id + ")";
            List<JSONObject> moduleDataBySearch = CrmApiUtil.getModuleDataBySearch(zohoRecord.getAccessToken(), searchUrl);
            if (moduleDataBySearch.size() > 0) {
                JSONObject jsonObject1 = moduleDataBySearch.get(0);
                String userId = jsonObject1.getString("id");
                jsonObject.put("id", userId);
            }
            jsonObject.put("Sign_Account_ID", newAccountId);
            url = "https://www.zohoapis.com.cn/crm/v3/User_Profile";
        } else if (type == 2) {
            jsonObject.put("id", id);
            jsonObject.put("accountId_c", newAccountId);
            url = "https://www.zohoapis.com.cn/crm/v3/Accounts";
        }
        updateData.add(jsonObject);
        paramsMap.put("data", updateData);
        log.info("数据更新 = " + new JSONObject(paramsMap));
        HttpUtil.putData(url, paramsMap);

        map.put("accountId", accountId);
        return ResultUtil.success(map);
    }

    @Override
    public ResultUtil generatorAccount(JSONObject incentiveData) {
        //System.out.println("zohoRecord.getAccessToken() = " + zohoRecord.getAccessToken());

        List<JSONObject> data = new ArrayList<>();
        // 销售总监
        JSONObject sales_director_c = incentiveData.getJSONObject("Sales_Director_c");
        if (Objects.nonNull(sales_director_c)) {
            String saleId = sales_director_c.getString("id");
            JSONObject saleDirectorData = getSaleDirectorData(zohoRecord.getAccessToken(), saleId);
            if (Objects.nonNull(saleDirectorData)) {
                saleDirectorData.put("type", 1);//
                saleDirectorData.put("typeName", 1);//甲方即销售总监
                saleDirectorData.put("id", saleId);
                saleDirectorData.put("name", sales_director_c.getString("name"));
                data.add(saleDirectorData);
            }
        }

        // 乙方-签约人
        JSONObject two_part1_c = incentiveData.getJSONObject("Two_Part1_c");
        if (Objects.nonNull(two_part1_c)) {
            String two_part1_id = two_part1_c.getString("id");
            JSONObject yiData = getSignPeopleData(zohoRecord.getAccessToken(), two_part1_id);
            if (Objects.nonNull(yiData)) {
                yiData.put("id", two_part1_id);
                yiData.put("typeName", 2);//乙方
                yiData.put("name", two_part1_c.getString("name"));
                yiData.put("type", 2);//
                data.add(yiData);
            }
        }

        // 丙方-签约人
        JSONObject the_Third_Party_c = incentiveData.getJSONObject("The_Third_Party_c");
        if (Objects.nonNull(the_Third_Party_c)) {
            String the_third_party_id = the_Third_Party_c.getString("id");
            JSONObject bingData = getSignPeopleData(zohoRecord.getAccessToken(), the_third_party_id);
            if (Objects.nonNull(bingData)) {
                bingData.put("id", the_third_party_id);
                bingData.put("typeName", 3);//丙方
                bingData.put("name", the_Third_Party_c.getString("name"));
                bingData.put("type", 2);//
                data.add(bingData);
            }
        }
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (JSONObject datum : data) {
            ResultUtil tempResult = callESignAccount(datum);
            if (!tempResult.getCode().equals(200)) {
                return tempResult;
            } else {
                Map<String, Object> tempMap = (Map<String, Object>) tempResult.getData();
                mapList.add(tempMap);
            }
        }
        return ResultUtil.success(mapList);
    }

    /**
     * 一步发起签署 上量奖励
     *
     * @param incentiveData crm上量奖励数据
     * @param fileName      文件名称
     * @param mapList       关键字坐标
     */
    public ResultUtil<String> launchESign(JSONObject incentiveData, String fileName, List<Map<String, Object>> mapList) {

        String fileId = (String) mapList.get(0).get("fileId");
        // 实名认证方式
        String personAvailableAuthTypes_c = incentiveData.getString("personAvailableAuthTypes_c");
        // 意愿认证
        String willTypes_c = incentiveData.getString("willTypes_c");
        // 省区经理
        String provinceId = "";
        JSONObject bizProvinceManager_c = incentiveData.getJSONObject("BizProvinceManager_c");
        if (Objects.nonNull(bizProvinceManager_c)) {
            provinceId = bizProvinceManager_c.getString("id");
        }
        // 所属人
        JSONObject owner = incentiveData.getJSONObject("shareuser"); // todo shareuser
        String ownId = owner.getString("id");


        // 请求参数
        // 一、flowInfo 类型：object 本次签署流程的基本信息
        Map<String, Object> flowInfo = new HashMap<>();
        flowInfo.put("businessScene", fileName);
        flowInfo.put("autoArchive", true);//是否自动归档
        flowInfo.put("autoInitiate", true);//是否自动开启,流程开启后才能发送短信通知)

        //flowConfigInfo  本次签署流程的任务信息配置
        Map<String, Object> flowConfigInfo = new HashMap<>();
        //flowConfigInfo.put("noticeDeveloperUrl", "http://81.70.161.35:8088/sign/incentive/noticeDeveloperUrl"); // 回调地址
        flowConfigInfo.put("noticeDeveloperUrl", "http://118.24.38.25:8088/sign/incentive/noticeDeveloperUrl"); // 回调地址
        flowConfigInfo.put("noticeType", "1"); // 签署通知方式 短信
        flowConfigInfo.put("signPlatform", "1"); // 签署平台 H5网页版方式进行签署

        //flowConfigInfo.put("willTypes", "CODE_SMS");
        //flowConfigInfo.put("redirectUrl", 1);
        //String[] psn = new String[]{"PSN_TELECOM_AUTHCODE"};
        String psnAuthTypes = StringUtils.isBlank(personAvailableAuthTypes_c) ? "PSN_TELECOM_AUTHCODE" : personAvailableAuthTypes_c;
        psnAuthTypes = TransferUtil.transferWill(psnAuthTypes);
        String[] psn = psnAuthTypes.split(",");
        flowConfigInfo.put("personAvailableAuthTypes", psn);
        flowInfo.put("flowConfigInfo", flowConfigInfo);
        //二、signers  array  签署方信息

        List<Map<String, Object>> signersList = new ArrayList<>();
        for (Map<String, Object> personMap : mapList) {
            Map<String, Object> signers = new HashMap<>();
            signers.put("platformSign", false);
            signers.put("signOrder", 1);
            //signerAccount object 签署方账号信息
            Map<String, Object> signerAccount = new HashMap<>();
            signerAccount.put("signerAccountId", personMap.get("accountId"));
            signerAccount.put("noticeType", 1);

            String wtsTemp = StringUtils.isBlank(willTypes_c) ? "CODE_SMS" : willTypes_c;
            wtsTemp = TransferUtil.transferTrueName(wtsTemp);
            String[] wts = wtsTemp.split(",");

            List<String> willTypes = new ArrayList<>();
            Collections.addAll(willTypes, wts);
            signerAccount.put("willTypes", willTypes);
            signers.put("signerAccount", signerAccount);

            //signfields array 签署方的签署区列表数据
            List<Map<String, Object>> signfieldsList = new ArrayList<>();
            Map<String, Object> signfields = new HashMap<>();
            signfields.put("assignedPosbean", true);   //是否固定指定的签署区位置
            signfields.put("autoExecute", false);
            signfields.put("fileId", fileId);
            signfields.put("sealType", 0); // 手绘签名
            signfields.put("signType", 1);//签署类型，0-不限，1-单页签署，2-骑缝签署
            Map<String, Object> posBean = new HashMap<>();
            posBean.put("posPage", personMap.get("pageIndex").toString());
            posBean.put("posX", personMap.get("posx"));
            posBean.put("posY", personMap.get("posy"));
            signfields.put("posBean", posBean);
            signfieldsList.add(signfields);

            signers.put("signfields", signfieldsList);

            signersList.add(signers);
        }

        //三、docs array 待签署文件信息
        List<Map<String, Object>> docsList = new ArrayList<>();
        Map<String, Object> docs = new HashMap<>();
        docs.put("fileId", fileId);
        docs.put("fileName", fileName);
        docs.put("encryption", 0);
        docsList.add(docs);

        ////四、copiers 抄送人列表 注：抄送人指不参与签署但需要查看签署文件的人，签署流程归档后抄送人收到通知。
        //List<Map<String, Object>> copiersList = new ArrayList<>();
        //if (provinceId.equals(ownId)) {
        //    Map<String, Object> cp1 = new HashMap<>();
        //    cp1.put("copierAccountId", provinceId);
        //    cp1.put("copierIdentityAccountType", 0);
        //    copiersList.add(cp1);
        //}
        //if (!provinceId.equals(ownId) && accountId != null) {
        //    Map<String, Object> cp2 = new HashMap<>();
        //    cp2.put("copierAccountId", accountId);
        //    cp2.put("copierIdentityAccountType", 0);
        //    copiersList.add(cp2);
        //}

        //总参数
        Map<String, Object> flowMap = new HashMap<>();
        flowMap.put("flowInfo", flowInfo);
        flowMap.put("signers", signersList);
        flowMap.put("docs", docsList);
        //if (copiersList.size() > 0) {
        //    flowMap.put("copiers", copiersList);
        //}

        JSONObject updateData = new JSONObject();
        updateData.put("EsignSendTime_c", DateUtil.getTodayHMByT()); // 发送电子签名时间

        String wtsTemp = StringUtils.isBlank(willTypes_c) ? "CODE_SMS" : willTypes_c;
        wtsTemp = TransferUtil.transferTrueName(wtsTemp);
        String[] wts = wtsTemp.split(",");

        JSONObject parameter = new JSONObject(flowMap);
        log.info("一步发起签署接口parameter = " + parameter.toJSONString());
        JSONObject jsonObject = ESignApiUtil.launchESign(this.parameter, environment, parameter);
        log.info("一步发起签署接口result = " + jsonObject.toJSONString());
        if (0 == jsonObject.getInteger("code")) {
            //{"code":0,"data":{"flowId":"f78d199fb54c4022b74fd2b7a9f09772"},"message":"成功"}
            JSONObject data = jsonObject.getJSONObject("data");
            String flowId = data.getString("flowId");

            updateData.put("flowId_c", flowId); // 签署流程id
            updateData.put("EsignStatus_c", "已发送"); // 签署状态

            // 实名认证方式
            String psnStr = TransferUtil.transferTrueNameString(psn);
            updateData.put("personAvailableAuthTypes_c", psnStr);

            // 意愿认证
            String willStr = TransferUtil.transferWillString(wts);
            updateData.put("willTypes_c", willStr);

            String incentiveId = incentiveData.getString("id");
            //修改上量奖励数据
            CrmApiUtil.updateIncentiveData(incentiveId, updateData);

            return ResultUtil.success(flowId);
        } else {
            return ResultUtil.error(jsonObject.toJSONString());
        }
    }

    @Override
    public void noticeDeveloper(String json) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        // 认证结束
        if ("SIGN_FLOW_FINISH".equals(jsonObject.getString("action")) &&
                "2".equals(jsonObject.getString("flowStatus"))) {
            log.info("===== 第五步【流程文档下载】=====");
            String incentiveId = "";
            String flowId = jsonObject.getString("flowId");
            log.info("flowId = " + flowId);
            JSONObject downloadFileResult = ESignApiUtil.downloadFile(parameter, environment, flowId);
            log.info("流程文档下载接口result = " + downloadFileResult.toJSONString());
            // {"code":0,"data":{"docs":[{"fileName":"张斌20230222-20231231南京药业股份有限公司(刘冲)帕立骨化醇注射液1ml-2μg - 5支-盒4市场推广服务协议[正常].doc","fileUrl":"https://esignoss.esign.cn/1111563786/8c12dcb7-4985-4a7c-858b-9218be9e587c/%E5%BC%A0%E6%96%8C20230222-20231231%E5%8D%97%E4%BA%AC%E8%8D%AF%E4%B8%9A%E8%82%A1%E4%BB%BD%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8%28%E5%88%98%E5%86%B2%29%E5%B8%95%E7%AB%8B%E9%AA%A8%E5%8C%96%E9%86%87%E6%B3%A8%E5%B0%84%E6%B6%B21ml-2%CE%BCg%20-%205%E6%94%AF-%E7%9B%924%E5%B8%82%E5%9C%BA%E6%8E%A8%E5%B9%BF%E6%9C%8D%E5%8A%A1%E5%8D%8F%E8%AE%AE%5B%E6%AD%A3%E5%B8%B8%5D.doc.pdf?Expires=1679985557&OSSAccessKeyId=LTAI4G23YViiKnxTC28ygQzF&Signature=2XHSDgNJDVStZwLMMZDwlfGwY20%3D","fileId":"e3365fd1235a4b6da157441eda5106f6"}]},"message":"成功"}
            if (0 == downloadFileResult.getInteger("code")) {
                JSONObject data = downloadFileResult.getJSONObject("data");
                JSONArray docs = data.getJSONArray("docs");
                List<JSONObject> list = docs.toJavaList(JSONObject.class);
                JSONObject temp = list.get(0);
                String fileName = temp.getString("fileName");
                String fileUrl = temp.getString("fileUrl");
                //String fileId = temp.getString("fileId");

                String filePath = FileUtil.getRelativeResourceFilePath();
                String fileFullPath = filePath + File.separator + fileName;

                try {
                    boolean boo = FileTransformation.downLoadFileByUrl(fileUrl, fileFullPath);
                    if (boo) {
                        log.info("文件生成成功");
                    } else {
                        log.info("文件生成失败");
                    }

                    // 根据flowId查 上量奖励id

                    String searchUrl = "https://www.zohoapis.com.cn/crm/v3/Incentive_Agreement/search?criteria=(flowId_c:equals:" + flowId + ")";
                    List<JSONObject> moduleDataBySearch = CrmApiUtil.getModuleDataBySearch(zohoRecord.getAccessToken(), searchUrl);
                    if (moduleDataBySearch.size() > 0) {
                        incentiveId = moduleDataBySearch.get(0).getString("id");
                    }

                    if (StringUtils.isNotBlank(incentiveId)) {
                        log.info("根据flowId查到的incentiveId = " + incentiveId);
                        // 存储到上量奖励中的附件,文件流方式
                        String url = "https://www.zohoapis.com.cn/crm/v3/Incentive_Agreement/" + incentiveId + "/Attachments";
                        log.info("url = " + url);
                        JSONObject uploadFileResult = HttpUtil.postFileByFileStream(zohoRecord.getAccessToken(), fileFullPath, url);
                        if (uploadFileResult.toJSONString().contains("SUCCESS")) {
                            log.info("附件传送成功");

                            JSONArray tempData = uploadFileResult.getJSONArray("data");
                            List<JSONObject> tempList = tempData.toJavaList(JSONObject.class);
                            String fileId = tempList.get(0).getJSONObject("details").getString("id");
                            // 存储上量奖励模块 签署文件ID字段
                            JSONObject updateData = new JSONObject();
                            updateData.put("fileId_c", fileId);
                            CrmApiUtil.updateIncentiveData(incentiveId, updateData);

                            // 删除temp文件
                            deleteTempFile();
                        } else {
                            log.info("附件传送失败，{}", uploadFileResult.toJSONString());
                        }
                        // 删除PDF临时文件
                        deletePDFFile();
                    } else {
                        log.info("incentiveId查询数据为空");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (StringUtils.isNotBlank(incentiveId)) {
                // 将E签宝数据更新到上量奖励数据中
                JSONObject updateData = new JSONObject();
                updateData.put("SignDate_c", DateUtil.getToday()); // 已签署时间
                updateData.put("EsignStatus_c", "已完成"); // 签署状态
                CrmApiUtil.updateIncentiveData(incentiveId, updateData);
            }

        }
    }

    @Override
    public ResultUtil updateAccount(Integer type, String id) {
        String accountId = ""; // 签署账号ID
        String email = ""; // 邮箱
        String mobile = ""; // 手机号
        String name = ""; // 姓名
        String url = "";
        if (type == 1) { // 用户信息
            List<JSONObject> userInfo = BiologicalApiUtil.getUserInfo(zohoRecord.getAccessToken(), id);
            JSONObject jsonObject = userInfo.get(0);
            accountId = jsonObject.getString("Sign_Account_ID");
            email = jsonObject.getString("User_Email");
            mobile = jsonObject.getString("Phone");
            name = jsonObject.getString("Name");
            url = "https://www.zohoapis.com.cn/crm/v3/User_Profile";
        } else if (type == 2) { // 基础档案
            List<JSONObject> userInfo = BiologicalApiUtil.getBasicFile(zohoRecord.getAccessToken(), id);
            JSONObject jsonObject = userInfo.get(0);
            accountId = jsonObject.getString("accountId_c");
            email = jsonObject.getString("MainEmail_c");
            mobile = jsonObject.getString("Phone");
            name = jsonObject.getString("Account_Name");
            url = "https://www.zohoapis.com.cn/crm/v3/Accounts";
        }
        log.info("修改E签宝账户,accountId = {},email = {},mobile = {},name = {}", accountId, email, mobile, name);
        JSONObject jsonObject = ESignApiUtil.updateAccountByID(parameter, environment, accountId, email, mobile, name);
        log.info("修改E签宝账户,result = {}", jsonObject);

        JSONObject updateJson = new JSONObject();
        updateJson.put("IsSync_c", false); // 是否重新同步签署ID
        Map<String, Object> paramsMap = new HashMap<>();
        JSONArray updateData = new JSONArray();
        updateJson.put("id", id);
        updateData.add(updateJson);
        paramsMap.put("data", updateData);
        log.info("修改用户信息、基础档案数据 = " + new JSONObject(paramsMap));
        JSONObject result = HttpUtil.putData(url, paramsMap);
        if (result.toJSONString().contains("SUCCESS")) {
            log.info("用户信息、基础档案数据修改成功");
        }
        return ResultUtil.success(jsonObject);
    }

    @Override
    public ResultUtil cancelAccount(String accountId) {
        log.info("个人账户注销 accountId = {}", accountId);
        JSONObject jsonObject = ESignApiUtil.cancelAccountByAccountId(parameter, environment, accountId);
        log.info("个人账户注销result = " + jsonObject.toJSONString());
        return ResultUtil.success(jsonObject);
    }


    @Override
    public ResultUtil updateIDCard(String accountId, Integer type, String id) {
        // 1 注销
        cancelAccount(accountId);

        // 2 新建
        String name = "";
        String phone = "";
        if (type == 1) { // 用户信息
            List<JSONObject> userInfo = BiologicalApiUtil.getUserInfo(zohoRecord.getAccessToken(), id);
            JSONObject jsonObject = userInfo.get(0);
            phone = jsonObject.getString("Phone");
            name = jsonObject.getString("Name");
        } else if (type == 2) { // 基础档案
            List<JSONObject> userInfo = BiologicalApiUtil.getBasicFile(zohoRecord.getAccessToken(), id);
            JSONObject jsonObject = userInfo.get(0);
            phone = jsonObject.getString("Phone");
            name = jsonObject.getString("Account_Name");
        }


        JSONObject account = ESignApiUtil.createAccount(parameter, environment, id, name, phone);
        log.info("创建个人账号接口result = " + account.toJSONString());
        if (account.getInteger("code") == 0) {
            JSONObject data = account.getJSONObject("data");
            String newAccountId = data.getString("accountId");
            log.info("accountId = " + newAccountId);

            // 存储 accountId
            Map<String, Object> paramsMap = new HashMap<>();
            JSONArray updateData = new JSONArray();
            JSONObject jsonObject = new JSONObject();

            String url = "";
            jsonObject.put("id", id);
            if (type == 1) {
                jsonObject.put("Sign_Account_ID", newAccountId);
                jsonObject.put("ID1", null); // 是否重新签署账号ID
                url = "https://www.zohoapis.com.cn/crm/v3/User_Profile";
            } else if (type == 2) {
                jsonObject.put("accountId_c", newAccountId);
                jsonObject.put("IsSync_c", false); // 是否重新签署账号ID
                url = "https://www.zohoapis.com.cn/crm/v3/Accounts";
            }
            updateData.add(jsonObject);
            paramsMap.put("data", updateData);
            log.info("数据更新 = " + new JSONObject(paramsMap));
            JSONObject result = HttpUtil.putData(url, paramsMap);
            if (result.toJSONString().contains("SUCCESS")) {
                log.info("用户信息、基础档案数据修改成功");
            }
        } else {
            return ResultUtil.error(account.toJSONString());
        }
        return ResultUtil.success();
    }
}
